package Unit

import (
	. "GameLogic/GameConfig"
	"GameLogic/Scene"
	"container/list"
)

type unitEventFunc func(unit *Unit, args ...interface{})

type Unit struct {
	Scene.BaseUnit
	Abilities  map[int]IAbility
	Weapons    []*Weapon
	CmdQueue   *CommandQueue
	unitEvents map[string]*list.List

	flags map[string]bool

	IsDie bool
}

func (unit *Unit) SetHP(newHP int) {
	unit.HP = newHP
	if unit.HP <= 0 {
		unit.IsDie = true
		unit.CallEvent("UnitDie")
	}
}

func NewUnit(unit *XmlUnit, uuid string, gamePlayerId int, scene *Scene.Scene) Scene.IUnit {
	newUnit := &Unit{}
	newUnit.HP = unit.HP
	newUnit.MP = unit.MP
	newUnit.UUID = uuid
	newUnit.GamePlayerId = gamePlayerId
	newUnit.Scene = scene
	newUnit.MoveSpeed = unit.MoveSpeed
	newUnit.IsDie = false
	//UnitEvents
	newUnit.unitEvents = make(map[string]*list.List)
	//UnitFlags
	newUnit.flags = unit.Flags
	//Ability
	newUnit.Abilities = make(map[int]IAbility)
	for abili := 0; abili < len(unit.Abilities); abili++ {
		elem := unit.Abilities[abili]
		abili := GetAbilityNewFunc(elem.Name())(elem)
		abili.GetAbilityInfo().AbiliUnit = newUnit
		newUnit.AddAbility(abili)
	}
	//Weapon
	newUnit.Weapons = make([]*Weapon, len(unit.Weapons))
	for wi := 0; wi < len(unit.Weapons); wi++ {
		elem := unit.Weapons[wi]
		weaponName, _ := elem.AttrValue("Name")
		newUnit.Weapons[wi] = NewWeapon(GetXmlWeapon(weaponName))
		newUnit.Weapons[wi].Init(newUnit)
	}
	return newUnit
}

func (unit *Unit) AddEvent(eventName string, eventFn unitEventFunc) {
	if unit.unitEvents[eventName] == nil {
		unit.unitEvents[eventName] = list.New()
	}
	unit.unitEvents[eventName].PushBack(eventFn)
}

func (unit *Unit) CallEvent(eventName string, args ...interface{}) {
	lst := unit.unitEvents[eventName]
	if lst != nil {
		for e := lst.Front(); e != nil; e = e.Next() {
			e.Value.(unitEventFunc)(unit, args)
		}
	}
	unit.Scene.Trigger.CallEvent(eventName, unit)
}

func (unit *Unit) Flag(flagkey string) bool {
	if v, ok := unit.flags[flagkey]; ok {
		return v
	}
	return false
}

func (unit *Unit) GetBaseUnit() *Scene.BaseUnit {
	return &unit.BaseUnit
}

func (this *Unit) GetCmdQueue() *CommandQueue {
	if this.CmdQueue == nil {
		this.CmdQueue = NewCommandQueue()
	}
	return this.CmdQueue
}

func (this *Unit) PushCmd(commandType int32, pushType int32, intArgs []int32, floatArgs []float32, strArgs []string) {

	if pushType == 1 {
		this.GetCmdQueue().Clear()
	}
	this.GetCmdQueue().Push(commandType, intArgs, floatArgs, strArgs)
}

func (this *Unit) AddAbility(abil IAbility) {
	this.Abilities[abil.GetId()] = abil
}

func (this *Unit) OnEnter() {
	for _, v := range this.Abilities {
		v.OnEnter()
	}
}

func (this *Unit) GetAbility(Id int) IAbility {
	return this.Abilities[Id]
}

func (this *Unit) Update() {
	for _, abili := range this.Abilities {
		abili.Update()
	}

	for _, weapon := range this.Weapons {
		weapon.Update()
	}
}
